<?php

/**
 * b2b168操作
 */
class Shanghui5
{
    //**** 定义私有变量 ****//

    // 用户信息相关
    private $userName;          // 用户账号
    private $userPass;          // 用户密码
    private $userCookies;       // 登录Cookies
    private $status = 0;        // 状态

    private $retNew;

    // 定义错误信息
    private $errorMsg;          // 错误信息

    // 系统选项相关
    private $options = array(
        'recordsFile' => './userRecords.json',   // 记录用户信息的文件
    );


    /**
     * 初始化函数
     * @param string $userName 用户账号
     * @param string $userPass 用户密码
     * @param string $userCookies 登录Cookies
     * @param array $options 配置选项信息
     */
    function __construct($userName, $userPass, $userCookies = null, $options = array())
    {
        $this->userName = $userName;  // 保存用户账号
        $this->userPass = $userPass;  // 保存用户密码

        // 识别并保存配置选项
        foreach ($options as $optKey => $optValue)
            $this->options[$optKey] = $optValue;

        // 检查保存用户信息的文件
        file_exists($this->options['recordsFile']) ?: file_put_contents($this->options['recordsFile'], '{}');

        // 设置并保存Cookies
        if (!$userCookies) {
            $userRecords = json_decode(file_get_contents($this->options['recordsFile']), true);
            if (!empty($userRecords[$this->userName]['Cookies']))
                $userCookies = $userRecords[$this->userName]['Cookies'];
        }

        $this->setCookie($userCookies) ?: $this->errorMsg = 'NotLogin';
    }

    /**
     * 获取上次操作的错误信息
     * @return string 错误信息描述
     */
    public function getErrorMsg()
    {
        return $this->errorMsg;
    }

    /**
     * 设置并验证用户Cookies
     * @param string $cookies 用户Cookies
     * @return boolean  true 表示已经保存, false 表示未登录
     */
    public function setCookie($cookies = null)
    {
        // 验证登录的地址
        $url = 'http://www.shanghui5.com/member/login.php';
        $header[] = "Referer: http://www.shanghui5.com/member/login.php";
        // 提交请求
        $retHtml = Get_Web_Contents($url, 'GET', '', $cookies, $header);

        if (isset($retHtml['Error'])) {
            $this->errorMsg = 'cUrl请求时出错';
            return false;
        }

        // 判断是否已经登录
        if (!stripos($retHtml['Body'], '免费注册')) {
            $this->userCookies = $cookies;
            $this->status = 1;
            return true;
        } else {
            $this->status = 0;
            $this->errorMsg = '账号未登录';
            return false;
        }
    }

    /**
     * 保存用户的Cookies
     */
    public function saveCookie()
    {
        if ($this->status <= 0) {
            $this->errorMsg = '登录状态不正确';
            return false;
        }
        $userRecords = json_decode(file_get_contents($this->options['recordsFile']), true);
        $userRecords[$this->userName]['Cookies'] = $this->userCookies;
        if (!file_put_contents($this->options['recordsFile'], json_encode($userRecords))) {
            $this->errorMsg = '保存到json文件失败';
            return false;
        }
        return true;
    }

    /**
     * 用户账号登录
     * @param  string $userName 需要登录的用户账号
     * @param  string $userPass 需要登录的用户密码
     * @return mixed            登录成功返回用户Cookies 失败返回 false
     */
    public function userLogin($userName = null, $userPass = null)
    {
        // 设置账号密码
        $userName ?: $userName = $this->userName;
        $userPass ?: $userPass = $this->userPass;

        // 登录提交的地址
        $url = 'http://www.shanghui5.com/member/login.php';
        $header[] = "Referer: http://www.shanghui5.com/member/login.php";
        $userRecords = json_decode(file_get_contents($this->options['recordsFile']), true);
        if (!file_put_contents($this->options['recordsFile'], json_encode($userRecords))) {
            $this->errorMsg = '保存到json文件失败';
            return false;
        }

        #验证码步骤
        $captcha_url = "http://www.shanghui5.com/api/captcha.png.php?action=image";
        $captcha = Get_Web_Contents($captcha_url, 'GET', '', '', $header);
        if (empty($captcha['Body'])) {
            $this->errorMsg = '验证码接口出错';
            return false;
        }
        $file = LIB_PATH . '/captcha.png';  #验证码保存的位置
        file_put_contents($file, $captcha['Body']);
        #获取验证码的 字符串
        $captcha_json = $this->captcha($file);
        $captcha_arr = json_decode($captcha_json, true);
        if (empty($captcha_arr['Result'])) {
            $this->errorMsg = '验证码接口出错';
            return false;
        }

        $captchaCode = $captcha_arr['Result']; #识别图片之后的验证码
        #设置 调用 验证码接口返回的cookie 信息
        $cookie = $captcha['Cookies'];
        $header['User-Agent'] = 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36';
        #提交的数据
        $data['forward'] = "http://www.shanghui5.com/";
        $data['option'] = "username";
        $data['username'] = $userName;
        $data['password'] = md5($userPass);
        $data['captcha'] = $captchaCode;
        $data['cookietime'] = 1;
        $data['goto'] = 1;
        $data['submit'] = ' 登 录 ';
        #验证码验证
        $url_ajax = "http://www.shanghui5.com/ajax.php";
        $data_ajax['action'] = 'captcha';
        $data_ajax['captcha'] = $captchaCode;
        $ret_ajax = Get_Web_Contents($url_ajax, 'POST', $data_ajax, $cookie, $header);

        #验证码判断，3为验证码 错误，0为成功
        if (!empty($ret_ajax['Body']) && $ret_ajax['Body'] != 0) {
            sleep(10);
            $this->userLogin($userName, $userPass);
        }
        // 提交登录数据
        $retHtml = Get_Web_Contents($url, 'POST', $data, $cookie, $header);

        if (!stripos($retHtml['Body'], '对象已移动')) {
            $this->errorMsg = "未匹配到登录返回信息";
            return false;
        }

        $this->userCookies = $retHtml['Cookies'];
        $this->status = 1;
        return $retHtml['Cookies'];
    }

    /**
     * 验证码验证接口
     * @param  string $image 图片所在地址
     * @return  string 返回通过识别的验证码字符串
     */
    public function captcha($image)
    {
        if (!is_file($image)) {
            $this->errorMsg = '没有验证码图片';
            return false;
        }
        $damaUrl = 'http://api.ysdm.net/create.json';
        $ch = curl_init();
        $postFields = array(
            'username' => 'w521521544',
            'password' => 'd5d86bb695e7da42eda7114ac411dcb7',
            'typeid' => 3040,    //4位的字母数字混合码   类型表http://www.ysdm.net/home/PriceType
            'timeout' => 60,    //中文以及选择题类型需要设置更高的超时时间建议90以上
            'softid' => 54725,    //改成你自己的
            'softkey' => 'aaffa5dc8c204170acf59290b339507d',    //改成你自己的
            'image' => new CURLFile($image)
        );

        curl_setopt($ch, CURLOPT_URL, $damaUrl);
        curl_setopt($ch, CURLOPT_HEADER, FALSE);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
        curl_setopt($ch, CURLOPT_TIMEOUT, 65);    //设置本机的post请求超时时间，如果timeout参数设置60 这里至少设置65
        curl_setopt($ch, CURLOPT_POST, TRUE);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $postFields);
        $result = curl_exec($ch);
        curl_close($ch);
        return $result;
    }


    /**
     * 判断new 页面是否还可以上传
     * @return mixed 返回还可以上传的条数
     */
    public function judgeNew()
    {
        $url = 'http://www.shanghui5.com/member/news.php';
        $cookie = $this->userCookies;

        // 读取页面内容
        $header[] = "Referer: http://www.shanghui5.com/member/news.php";
        $header['User-Agent'] = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36";
        $retHtml = Get_Web_Contents($url, 'GET', '', $cookie, $header);

        #提取条数
        preg_match("#<span class=\"f_b f_blue\">(.*?)</span>#", $retHtml['Body'], $mess);

        #大于100条的就直接说yes ，确定可以直接读取
        if ($mess[1] > 100) {
            $this->retNew = 'yes';
        } else {
            $this->retNew = 'no';
        }
        return $mess[1];
    }

    /**
     * 上传文章 判断
     * @param string $postKeyword 关键字
     * @param string $postContent 内容
     * @param array $columnList 传输的栏目信息
     * @param int $num 当前传输的个数
     * @return bool  上传成功还是不成功
     */
    public function postCondition($postKeyword, $postContent, $columnList, $num)
    {
        #如果 小于等于 100 条，就读取 new 里面的信息 ，否则读取 my 里面的信息
        if ($num <= 100) {
            #如果 确定是 可以传 100 条的就进行传输，
            if ($this->retNew == 'yes') {
                $addPostRet = $this->postAdd($postKeyword, $postContent, $columnList['new']['url'], $columnList['new']['param']);
            } elseif ($this->retNew == 'no') {
                $addPostRet = $this->postAdd($postKeyword, $postContent, $columnList['my']['url'], $columnList['my']['param']);
            } else {
                #如果不能确定的，就读取下 页面，然后看里面剩下多少条，要是 剩下 不足100 条就 没添加一条查看一次
                $limitNum = $this->judgeNew();
                if ($limitNum > 0) {
                    $addPostRet = $this->postAdd($postKeyword, $postContent, $columnList['new']['url'], $columnList['new']['param']);
                } else {
                    $this->retNew = 'no';
                    $addPostRet = $this->postAdd($postKeyword, $postContent, $columnList['my']['url'], $columnList['my']['param']);
                }
            }
        } else {
            $addPostRet = $this->postAdd($postKeyword, $postContent, $columnList['my']['url'], $columnList['my']['param']);
        }

        return $addPostRet;
    }

    /**
     * 发布文章
     * @param  string $title 文章标题
     * @param  string $body 文章内容
     * @return boolean  是否发送成功
     */
    public function postAdd($title, $body, $postUrl = '', $param = array())
    {
        $cookie = $this->userCookies;

        #提交的数据
        $param['post']['title'] = $title;      // 文章标题
        $param['post']['content'] = $body;     // 文章内容

        $header['Host'] = "Host: www.shanghui5.com";
        $header['User-Agent'] = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36";
        $header['Referer'] = "Referer: {$param['forward']}";
        $retHtml = Get_Web_Contents($postUrl, 'POST', http_build_query($param), $cookie, $header);


        // 判断是否成功,获取返回的cookie信息，
        // 要是有添加成功就表示已经添加成功，否则返回报错信息
        $role = '#c8w_dmsg=(.*?);#';
        preg_match($role, $retHtml['Cookies'], $retStr);

        //  未知错误
        if (!isset($retStr[1])) {
            $this->errorMsg = '未知错误';
            return false;
        }

        $retCode = trim(urldecode($retStr[1]));
        if ($retCode == '添加成功') {
            return true;
        } else {
            $this->errorMsg = $retCode;
            return false;
        }
    }


    /**
     * 获取文章今天的列表，默认每页20条
     * @param  integer $page 页码
     * @param  string $getUrl 要获取的页面地址
     * @param  int $flush 读取的次数
     * @return string 所有地址,标题
     */
    public function getPostList($page = 1, $getUrl, $flush = 1)
    {
        # 拼接读取地址
        $url = "{$getUrl}&page={$page}";
        $cookie = $this->userCookies;

        # 读取页面内容
        $header[] = "Referer: http://www.shanghui5.com/member/my.php?mid=7";
        $header['User-Agent'] = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36";
        $retHtml = Get_Web_Contents($url, 'GET', '', $cookie, $header);

        #如果没有 body 的内容就再读取2次，防止疏漏，如果真的没有内容就返回 false
        if (empty($retHtml['Body']) && $flush <= 3) {
            sleep(3);
            //$this->getPostList($page, $getUrl, ++$flush);return的数据呢
        }elseif(empty($retHtml['Body'])){
            $this->errorMsg = "获取列表信息出错了";
            return false;
        }

        #获取包括 链接id 时间 还有 标题
        $role_line = '#(<input type="checkbox" name="itemid\[\]" value="(.*?)")|(title="更新时间 (.*?)">)|(class="t"(.*?)<\/a>)#';
        preg_match_all($role_line, $retHtml['Body'], $mess);

        $messLink = array_merge(array_filter($mess[2])); #链接的value
        $messTime = array_merge(array_filter($mess[4])); #发布时间
        $messTitle = array_merge(array_filter($mess[6])); #标题


        #判断如果 获取页面的 数量不是20条的话，就进行再次读取,不过最多再读取2次
        if (count($messLink) != 20 && $flush <= 3) {
            sleep(3);
            $this->getPostList($page, $getUrl, ++$flush);
        }

        $todayTime = date('Y-m-d');
        $retList = array();
        foreach ($messTime as $key => $value) {
            $postTime = date('Y-m-d', strtotime($value));
            if ($postTime == $todayTime) {
                if (strpos($getUrl, '/news.php')) {
                    $retList['info'][] = "http://qiye.shanghui5.com/szjznkyy/news/itemid-{$messLink[$key]}.shtml"; #PC版
                    $retList['title'][] = str_replace(" target=\"_blank\">", "", $messTitle[$key]);
                } elseif (strpos($getUrl, '/my.php')) {
                    $retList['info'][] = "http://www.shanghui5.com/quote/show-{$messLink[$key]}.html"; #PC版
                    $retList['wap'][] = "http://m.shanghui5.com/7-0-{$messLink[$key]}-1.html"; #手机版
                    $retList['title'][] = str_replace(">", "", $messTitle[$key]);
                }

            }
        }

        // 分割每条记录
        return $retList;
    }


    /**
     * 获取发布文章的所有URL 和 标题 列表，并且进行保存
     * @param string $postList 列表信息，包括链接 还有 标题
     * @return bool|string
     */
    public function savePostUrl_Title($postList)
    {
        $userName = $this->userName;
        $saveErro = "";

        $len = count($postList['info']);
        $titleList = array();
        for ($j = 0; $j < $len; $j++) {
            $titleList[] = $postList['title'][$j];

            //获取关键词（标题）
            if (!empty($postList['wap'])) {
                $temp = array($postList['info'][$j], $postList['wap'][$j], $postList['title'][$j]);
            } else {
                $temp = array($postList['info'][$j], $postList['title'][$j]);

            }
            $hash = implode(",", $temp);
            unset($temp);
            $res = file_put_contents(POST_URL_KEY_LIST . $userName . ".csv", $hash . "\n", FILE_APPEND); //将每条的数据添加到文件

            //每日记录
            file_put_contents(POST_LOG_PATH . date('m-d') . ".csv", $hash . "\n", FILE_APPEND);
            if (!$res) $saveErro = true;
        }
        $json_titleList = json_encode($titleList);
        return ($saveErro === true) ? false : $json_titleList;
    }


    /**
     * 单独保存关键词
     * @param string $json_titleList 标题列表
     * @return bool 成功返回ture，失败返回 false
     */
    public function saveKey($json_titleList)
    {
        $userName = $this->userName;
        $titleList = json_decode($json_titleList, true);
        $str_title = implode(",", $titleList);
        $res = file_put_contents(POST_KEY_LOG . "{$userName}_key.csv", $str_title . ",", FILE_APPEND);
        return ($res == false) ? false : true;
    }


    /**
     * @param int $pageAll 要循环的次数
     * @param array $columnList 要调用的栏目地址等信息
     * @param string $userName 用户名，方便输出
     */
    public function writeLog($pageAll, $columnList, $userName)
    {
        for ($i = 1; $i <= $pageAll; $i++) {
            #调用 第几页的  数据
            $postList = $this->getPostList($i, $columnList['url']); //获取已发布文章的链接和标题
            if (!empty($postList['info'][0])) {
                #保存已发布的文章的链接和关键词
                $retInfo = $this->savePostUrl_Title($postList); #成功返回 标题列表
                if ($retInfo === false) print_r("{$userName}··· 第{$i}页的链接及标题未保存完整\n");
                else {
                    print_r("{$userName}··· 第{$i}页的链接及标题已保存至" . POST_URL_KEY_LIST . $userName . ".csv\n");
                    //单独保存已发布的关键词
                    $json_titleList = $retInfo;
                    $ret = $this->saveKey($json_titleList);
                    if ($ret) print_r("{$userName}··· 第{$i}页的标题已保存至" . POST_KEY_LOG . $userName . "_key.csv\n");
                    else print_r("{$userName}··· 第{$i}页的标题保存失败\n");
                }
            } else {
                print_r("${userName}··· 获取第{$i}页链接失败\n");
            }
        }
    }
}







